﻿using System;
using Microsoft.Win32;
using System.Runtime.InteropServices;
using System.IO;
using System.Windows.Forms;


namespace SenseUtil
{
    class SenseControl
    {
        #region constants
        public const int HWND_BROADCAST = 0xffff;
        public const int WM_WININICHANGE = 0x001A;
        const string CSTR_RegistryKey_HKLMTodaySetting = @"Software\Microsoft\Today\Items\HTC Sense";
        const string CSTR_RegistryName_TodayHTCSense = "Enabled";
        const string CSTR_ManilaFullPath = @"\Windows\ManilaFull.xml";
        const string CSTR_RegistryKey_HKLMSenseConfig = @"Software\HTC\Manila\Configuration";
        #endregion

        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("coredll.dll", SetLastError = true)]
        static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        #region Public Functions
        #region Control Sense
        public static void StopManila()
        {
            RegistryKey key = Registry.LocalMachine.OpenSubKey
              (CSTR_RegistryKey_HKLMTodaySetting, true);

            //Check if the key was opened correctly before using it
            if (key != null)
            {
                key.SetValue(CSTR_RegistryName_TodayHTCSense, 0);
                key.Close();
            }
            else
            {
                MessageBox.Show("Registry Key was locked, you will need to manually Stop Manila by removing it from the Home Page (via Settings>Home>Items)", "Unable to Stop Manila");
            }

            System.Threading.Thread.Sleep(2000);

            PostMessage((IntPtr)HWND_BROADCAST, WM_WININICHANGE, (IntPtr)0xF2, (IntPtr)0);
            PostMessage((IntPtr)HWND_BROADCAST, WM_WININICHANGE, (IntPtr)0xF2, (IntPtr)0);
            //  This is required or manila is enabled before it's fully disabled,
            //  so doesn't restart
            System.Threading.Thread.Sleep(2000);
        }

        public static void StartManila()
        {
            RegistryKey key = Registry.LocalMachine.OpenSubKey
                (CSTR_RegistryKey_HKLMTodaySetting, true);

            //Check if the key was opened correctly before using it
            if (key != null)
            {
                key.SetValue(CSTR_RegistryName_TodayHTCSense, 1);
                key.Close();
            }
            else
            {
                MessageBox.Show("Registry Key was locked, you will need to manually Start Manila by re-adding it to the Home Page (via Settings>Home>Items)", "Unable to Start Manila");
            }

            PostMessage((IntPtr)HWND_BROADCAST, WM_WININICHANGE, (IntPtr)0xF2, (IntPtr)0);
            PostMessage((IntPtr)HWND_BROADCAST, WM_WININICHANGE, (IntPtr)0xF2, (IntPtr)0);
        }

        public static void RestartManila()
        {
            //Diable Manila
            StopManila();

            //Start Manila
            StartManila();
        }

        public static void ResetManila()
        {
            //Disable
            StopManila();

            //Force manilafull.xml to be regenerated
            DeleteManilaFull();

            //Start Manila
            StartManila();
        }

        public static void FullResetManila()
        {
            //Disable
            StopManila();

            //Force manilafull.xml to be regenerated
            DeleteManilaFull();

            //Delete the registry keys
            DeleteConfigurationKeys();

            //Start Manila
            StartManila();
        }

        [DllImport("coredll.dll")]

        public static extern int KernelIoControl(int dwIoControlCode, IntPtr lpInBuf, int nInBufSize, IntPtr lpOutBuf, int nOutBufSize, ref int lpBytesReturned);

        private static int CTL_CODE(int DeviceType, int Func, int Method, int Access)
        {

            return (DeviceType << 16) | (Access << 14) | (Func << 2) | Method;

        }
        // Reset Pocket PC code used from: http://www.codeproject.com/KB/smart/restartwidnowsmobile.aspx
        public static int ResetPocketPC()
        {
            const int FILE_DEVICE_HAL = 0x101;

            const int METHOD_BUFFERED = 0;

            const int FILE_ANY_ACCESS = 0;

            int bytesReturned = 0;

            int IOCTL_HAL_REBOOT;

            IOCTL_HAL_REBOOT = CTL_CODE(FILE_DEVICE_HAL, 15, METHOD_BUFFERED, FILE_ANY_ACCESS);

            return KernelIoControl(IOCTL_HAL_REBOOT, IntPtr.Zero, 0, IntPtr.Zero, 0, ref bytesReturned);

        }
        #endregion
        #region Determine Sense State
        public static bool isSenseRunning()
        {
            bool running = false;

            RegistryKey key = Registry.LocalMachine.OpenSubKey
             (CSTR_RegistryKey_HKLMTodaySetting, true);

            //Avoid exception if key not present
            if (key != null)
            {
                //Check the registry value for the today plugin
                if ((int)key.GetValue(CSTR_RegistryName_TodayHTCSense, 0) == 1)
                {
                    running = true;
                }

                key.Close();
            }
            return running;
        }

        public static bool isManilaFullPresent()
        {
            bool present = false;
            //Check to see if file is present
            if (File.Exists(CSTR_ManilaFullPath))
            {
                present = true;
            }

            return present;
        }
        public static bool isConfigKeyPresent()
        {
            bool present = false;
            //Check that the keys exist
            RegistryKey key = Registry.LocalMachine.OpenSubKey(CSTR_RegistryKey_HKLMSenseConfig);
            if (key != null)
            {
                key.Close();
                present = true;
            }

            return present;
        }
        #endregion
        #endregion

        #region Private Functions
        private static bool DeleteManilaFull()
        {
            bool filedeleted;
            //If file present delete it
            if (File.Exists(CSTR_ManilaFullPath))
            {
                try
                {
                    File.Delete(CSTR_ManilaFullPath);
                }
                catch
                {
                    MessageBox.Show("Unable to delete ManilaFull.xml! Has this file been cooked into the ROM by mistake or be in use by another program?");
                }

            }

            //Check it was deleted
            if (File.Exists(CSTR_ManilaFullPath))
            {
                filedeleted = true;
            }
            else
            {
                filedeleted = false;
            }
            return filedeleted;
        }

        private static bool DeleteConfigurationKeys()
        {
            bool keysDeleted;

            //Check that the keys exist
            RegistryKey key = Registry.LocalMachine.OpenSubKey(CSTR_RegistryKey_HKLMSenseConfig);
            if (key != null)
            {
                key.Close();
                try
                {
                    Registry.LocalMachine.DeleteSubKeyTree(CSTR_RegistryKey_HKLMSenseConfig);
                }
                catch
                {
                    MessageBox.Show("Unable to delete Configuration Keys");
                }
            }

            //Check it was deleted
            key = Registry.LocalMachine.OpenSubKey(CSTR_RegistryKey_HKLMSenseConfig);
            if (key == null)
            {
                keysDeleted = true;
            }
            else
            {
                keysDeleted = false;
            }

            return keysDeleted;
        }
        #endregion
    }
}
